/*
 * Copyright � 2002-2011 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using NUnit.Framework;

namespace Spring.Expressions;

/// <summary>
///
/// </summary>
/// <author>Erich Eichinger</author>
[TestFixture]
public class FunctionNodeTests
{
    [Test]
    public void ExecutesLambdaFunction()
    {
        Dictionary<string, object> vars = new Dictionary<string, object>();
        Expression.RegisterFunction("ident", "{|n| $n}", vars);

        FunctionNode fn = new FunctionNode();
        fn.Text = "ident";
        StringLiteralNode str = new StringLiteralNode();
        str.Text = "theValue";
        fn.addChild(str);

        IExpression exp = fn;
        Assert.AreEqual(str.Text, exp.GetValue(null, vars));
    }

    [Test]
    public void ExecutesDelegate()
    {
        Dictionary<string, object> vars = new Dictionary<string, object>();
        vars["concat"] = new TestCallback(Concat);

        FunctionNode fn = new FunctionNode();
        fn.Text = "concat";
        StringLiteralNode str = new StringLiteralNode();
        str.Text = "theValue";
        fn.addChild(str);
        StringLiteralNode str2 = new StringLiteralNode();
        str2.Text = "theValue";
        fn.addChild(str2);

        IExpression exp = fn;
        Assert.AreEqual(string.Format("{0},{1},{2}", this.GetHashCode(), str.Text, str2.Text), exp.GetValue(null, vars));
    }

    private delegate string TestCallback(string arg1, string arg2);

    private string Concat(string arg1, string arg2)
    {
        return string.Format("{0},{1},{2}", this.GetHashCode(), arg1, arg2);
    }

    [Category("Performance")]
    [Test, Explicit]
    public void ExecutesDelegatePerformance()
    {
        Dictionary<string, object> vars = new Dictionary<string, object>(5);
        WaitCallback noop = delegate(object arg)
        {
            // noop
        };
        vars["noop"] = noop;

        FunctionNode fn = new FunctionNode();
        fn.Text = "noop";
        StringLiteralNode str = new StringLiteralNode();
        str.Text = "theArg";
        fn.addChild(str);

        int ITERATIONS = 10000000;

        StopWatch watch = new StopWatch();
        using (watch.Start("Duration Direct: {0}"))
        {
            for (int i = 0; i < ITERATIONS; i++)
            {
                ((WaitCallback) vars["noop"])(str.getText());
            }
        }

        using (watch.Start("Duration SpEL: {0}"))
        {
            for (int i = 0; i < ITERATIONS; i++)
            {
                fn.GetValue(null, vars);
            }
        }
    }
}
